#!/usr/bin/env python

from xmlrpclib import ServerProxy,Fault,ProtocolError
from contrib import irclib
import time
import ConfigParser

class IrcBot:

	def __init__(self):

		self.stop = False
		self.proxy_online = False
		self.admins = []
		
		# init default config
		self.config = ConfigParser.ConfigParser()
		self.config.add_section('backend')
		self.config.set('backend', 'url', '')
		self.config.add_section('admin')
		self.config.set('admin', 'password', 'admin')
		self.config.add_section('irc')
		self.config.set('irc', 'user', 'fgs-bot')
		self.config.set('irc', 'host', 'localhost')
		self.config.set('irc', 'port', '6667')
		self.config.set('irc', 'channels', '#fgs')

		# read/save config
		self.config.read('fgs-bot.ini')
		self.config_save()

		# read config
		self.host = self.config.get('irc', 'host')
		self.port = self.config.getint('irc', 'port')
		self.user = self.config.get('irc', 'user')
		self.channels = self.config.get('irc', 'channels').split(':')
		self.uri_backend = self.config.get('backend', 'url')

		# prepare irc
		self.irc = irclib.IRC()
		self.irc.add_global_handler('pubmsg', self._pubmsg, 1000)
		self.irc.add_global_handler('privmsg', self._privmsg, 1000)
		self.server = self.irc.server()

	def init_proxy(self):
		
		if self.proxy_online:
			self.proxy_online = False
		try:
			print "bot> prepare connection on backend"
			self.proxy = ServerProxy(self.uri_backend)
			self.proxy_online = True
		except:
			self.proxy_online = False

	def run(self):
	
		self.init_proxy()

		print "bot> connect to %s:%d" % (self.host, self.port)
		self.server.connect(self.host, self.port, self.user)
		time.sleep(2)
		self.irc.process_once()

		for chan in self.channels:
			print "bot> join %s" % (chan)
			self.server.join(chan)
			self.irc.process_once()

		while not self.stop:
			self.irc.process_once()

		self.disconnect()

	def disconnect(self):
			 
		print "bot> stopped"
		self.server.disconnect()
		self.irc.process_once()

	def _pubmsg(self, c, e):
		chan = e.target()
		nick = e.source().split('!')[0]
		msg = e.arguments()[0]
		self.process_msg(msg, chan, e.source())

	def _privmsg(self, c, e):
		nick = e.source().split('!')[0]
		msg = e.arguments()[0]
		self.process_msg(msg, None, e.source())

	def _get_nick(self, user):
		return user.split('!')[0]

	def send(self, msg, chan):
		self.server.send_raw("PRIVMSG %s :%s" % (chan, msg))
	
	def is_admin(self, user):
		try:
			self.admins.index(user)
			return True
		except:
			return False

	def config_save(self):
		self.config.write(file('fgs-bot.ini', 'w'))
	
	def process_msg(self, msg, chan=None, user=None):
		cmd = msg.split(' ')[0].lower()
		msg = msg.lstrip(cmd).lstrip(' ')

		if user and not chan:

			# identify admin
			if cmd == 'identify':
				password = msg.split(' ')[0]
				if password == self.config.get('admin', 'password'):
					self.admins.append(user)
					self.send("Welcome my lord", self._get_nick(user))
				else:
					self.send("Password incorrect", self._get_nick(user))

			# update config
			elif cmd == 'set':
				
				if not self.is_admin(user):
					self.send("Access denied", self._get_nick(user))
					return
					
				s = msg.split(' ')
				if len(s) == 3:
					section = s[0]
					key = s[1]
					value = s[2]
					self.config.set(section, key, value)
				else:
					self.send("Usage: set <SECTION> <KEY> <VALUE>", self._get_nick(user))

			# save config
			elif cmd == 'save':

				if not self.is_admin(user):
					self.send("Access denied", self._get_nick(user))
					return
					
				self.config_save()
				self.send("Configuration saved", self._get_nick(user))

			# restart
			elif cmd == 'restart':
				
				if not self.is_admin(user):
					self.send("Access denied", self._get_nick(user))
					return
		
				self.stop = True

			# show config
			elif cmd == 'showconfig':
				
				if not self.is_admin(user):
					self.send("Access denied", self._get_nick(user))
					return

				for section in self.config.sections():
					for key, value in self.config.items(section):
						self.send("%s : %s = %s" % (section, key, value), self._get_nick(user))

		# public chan
		elif chan:

			# test if proxy is online
			if not self.proxy_online:
				return

			# show info about player
			if cmd == '!info':
				who = msg.split(' ')[0]
				info = self.proxy.user.info(who)
				if not info:
					self.send("No info available for %s" % (who), chan)
				else:
					print info
					self.send("Nickname   : %s" % (info['login']), chan)
					self.send("Registered : %s (%d days ago)" % (info['dateRegistered'], int(info['daysRegistered'])), chan)
					if info['website']:
						self.send("Website    : %s" % (info['website']), chan)
					if len(info['games']):
						self.send("Scores     :", chan)
						for game in info['games']:
							self.send(" - %s : %d point(s) over %d match(s)" % (game, info['games'][game]['score'], info['games'][game]['count']), chan)
				
	

# main process
if __name__ == "__main__":
	stop = False
	while not stop:
		try:
			bot = IrcBot()
			bot.run()
		except KeyboardInterrupt:
			print 'bot> control+c catched, waiting to stop'
			bot.stop = True
			stop = True
			bot.disconnect()
			continue
